﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using H2.DataTypes;
using H2.Streams;

namespace Mystery.SCNR
{
    public class LevelData
    {
        public const int Size = 24;
        public const int Offset = 920;

        public Dependancy LevelDescription;

        public CampaignLevelData CampaignLevel;
        public MultiplayerLevelData MultiplayerLevel;

        public class CampaignLevelData
        {
            public const int Size = 2896;
            public const int Offset = 8;

            public int CampaignID;
            public int MapID;
            public Dependancy PreviewImage;
            public byte[] EnglishName;
            public byte[] JapaneseName;
            public byte[] GermanName;
            public byte[] FrenchName;
            public byte[] SpanishName;
            public byte[] ItalianName;
            public byte[] KoreanName;
            public byte[] ChineseName;
            public byte[] PortugueseName;
            public byte[] EnglishDescription;
            public byte[] JapaneseDescription;
            public byte[] GermanDescription;
            public byte[] FrenchDescription;
            public byte[] SpanishDescription;
            public byte[] ItalianDescription;
            public byte[] KoreanDescription;
            public byte[] ChineseDescription;
            public byte[] PortugueseDescription;

            public void ReadFrom(MapStream map)
            {
                CampaignID = map.ReadInt32();
                MapID = map.ReadInt32();
                PreviewImage = map.ReadDependancy();
                EnglishName = map.ReadBytes(64);
                JapaneseName = map.ReadBytes(64);
                GermanName = map.ReadBytes(64);
                FrenchName = map.ReadBytes(64);
                SpanishName = map.ReadBytes(64);
                ItalianName = map.ReadBytes(64);
                KoreanName = map.ReadBytes(64);
                ChineseName = map.ReadBytes(64);
                PortugueseName = map.ReadBytes(64);
                EnglishDescription = map.ReadBytes(256);
                JapaneseDescription = map.ReadBytes(256);
                GermanDescription = map.ReadBytes(256);
                FrenchDescription = map.ReadBytes(256);
                SpanishDescription = map.ReadBytes(256);
                ItalianDescription = map.ReadBytes(256);
                KoreanDescription = map.ReadBytes(256);
                ChineseDescription = map.ReadBytes(256);
                PortugueseDescription = map.ReadBytes(256);
            }

            public void WriteTo(BaseStream stream)
            {
                stream.Write(CampaignID);
                stream.Write(MapID);
                stream.Write(PreviewImage.Class);
                stream.Write(0);
                stream.Write(EnglishName);
                stream.Write(JapaneseName);
                stream.Write(GermanName);
                stream.Write(FrenchName);
                stream.Write(SpanishName);
                stream.Write(ItalianName);
                stream.Write(KoreanName);
                stream.Write(ChineseName);
                stream.Write(PortugueseName);
                stream.Write(EnglishDescription);
                stream.Write(JapaneseDescription);
                stream.Write(GermanDescription);
                stream.Write(FrenchDescription);
                stream.Write(SpanishDescription);
                stream.Write(ItalianDescription);
                stream.Write(KoreanDescription);
                stream.Write(ChineseDescription);
                stream.Write(PortugueseDescription);
            }
        }

        public class MultiplayerLevelData
        {
            public const int Size = 3174;
            public const int Offset = 16;

            public int MapID;
            public Dependancy PreviewImage;
            public byte[] EnglishName;
            public byte[] JapaneseName;
            public byte[] GermanName;
            public byte[] FrenchName;
            public byte[] SpanishName;
            public byte[] ItalianName;
            public byte[] KoreanName;
            public byte[] ChineseName;
            public byte[] PortugueseName;
            public byte[] EnglishDescription;
            public byte[] JapaneseDescription;
            public byte[] GermanDescription;
            public byte[] FrenchDescription;
            public byte[] SpanishDescription;
            public byte[] ItalianDescription;
            public byte[] KoreanDescription;
            public byte[] ChineseDescription;
            public byte[] PortugueseDescription;
            public byte[] ScenarioPath;
            public int SortOrder;
            public byte Flags;
            public byte[] unused0;
            public byte MaxTeamsNone;
            public byte MaxTeamsCTF;
            public byte MaxTeamsSlayer;
            public byte MaxTeamsOddball;
            public byte MaxTeamsKOTH;
            public byte MaxTeamsRace;
            public byte MaxTeamsHeadhunter;
            public byte MaxTeamsJuggernaught;
            public byte MaxTeamsTerritories;
            public byte MaxTeamsAssault;
            public byte[] unused1;

            public void ReadFrom(MapStream map)
            {
                MapID = map.ReadInt32();
                PreviewImage = map.ReadDependancy();
                EnglishName = map.ReadBytes(64);
                JapaneseName = map.ReadBytes(64);
                GermanName = map.ReadBytes(64);
                FrenchName = map.ReadBytes(64);
                SpanishName = map.ReadBytes(64);
                ItalianName = map.ReadBytes(64);
                KoreanName = map.ReadBytes(64);
                ChineseName = map.ReadBytes(64);
                PortugueseName = map.ReadBytes(64);
                EnglishDescription = map.ReadBytes(256);
                JapaneseDescription = map.ReadBytes(256);
                GermanDescription = map.ReadBytes(256);
                FrenchDescription = map.ReadBytes(256);
                SpanishDescription = map.ReadBytes(256);
                ItalianDescription = map.ReadBytes(256);
                KoreanDescription = map.ReadBytes(256);
                ChineseDescription = map.ReadBytes(256);
                PortugueseDescription = map.ReadBytes(256);
                ScenarioPath = map.ReadBytes(256);
                SortOrder = map.ReadInt32();
                Flags = map.ReadByte();
                unused0 = map.ReadBytes(3);
                MaxTeamsNone = map.ReadByte();
                MaxTeamsCTF = map.ReadByte();
                MaxTeamsSlayer = map.ReadByte();
                MaxTeamsOddball = map.ReadByte();
                MaxTeamsKOTH = map.ReadByte();
                MaxTeamsRace = map.ReadByte();
                MaxTeamsHeadhunter = map.ReadByte();
                MaxTeamsJuggernaught = map.ReadByte();
                MaxTeamsTerritories = map.ReadByte();
                MaxTeamsAssault = map.ReadByte();
                unused1 = map.ReadBytes(7);
            }

            public static MultiplayerLevelData Generate(LevelData.CampaignLevelData campaignLevelData, int baseCount)
            {
                MultiplayerLevelData l = new MultiplayerLevelData();
                l.MapID = campaignLevelData.MapID;
                l.PreviewImage = campaignLevelData.PreviewImage;
                l.EnglishName = campaignLevelData.EnglishName;
                l.JapaneseName = campaignLevelData.JapaneseName;
                l.GermanName = campaignLevelData.GermanName;
                l.FrenchName = campaignLevelData.FrenchName;
                l.SpanishName = campaignLevelData.SpanishName;
                l.ItalianName = campaignLevelData.ItalianName;
                l.KoreanName = campaignLevelData.KoreanName;
                l.ChineseName = campaignLevelData.ChineseName;
                l.PortugueseName = campaignLevelData.PortugueseName;
                l.EnglishDescription = campaignLevelData.EnglishDescription;
                l.JapaneseDescription = campaignLevelData.JapaneseDescription;
                l.GermanDescription = campaignLevelData.GermanDescription;
                l.FrenchDescription = campaignLevelData.FrenchDescription;
                l.SpanishDescription = campaignLevelData.SpanishDescription;
                l.ItalianDescription = campaignLevelData.ItalianDescription;
                l.KoreanDescription = campaignLevelData.KoreanDescription;
                l.ChineseDescription = campaignLevelData.ChineseDescription;
                l.PortugueseDescription = campaignLevelData.PortugueseDescription;
                l.ScenarioPath = new byte[256];
                l.unused0 = new byte[3];
                l.unused1 = new byte[8];
                l.MaxTeamsNone = 0;
                l.MaxTeamsCTF = (byte)baseCount;
                l.MaxTeamsSlayer = 8;
                l.MaxTeamsOddball = 8;
                l.MaxTeamsKOTH = 8;
                l.MaxTeamsRace = 8;
                l.MaxTeamsHeadhunter = 8;
                l.MaxTeamsJuggernaught = 8;
                l.MaxTeamsTerritories = 8;
                l.MaxTeamsAssault = (byte)baseCount;

                return l;
            }

            public void WriteTo(BaseStream stream)
            {
                stream.Write(MapID);
                stream.Write(PreviewImage.Class);
                stream.Write(0);
                stream.Write(EnglishName);
                stream.Write(JapaneseName);
                stream.Write(GermanName);
                stream.Write(FrenchName);
                stream.Write(SpanishName);
                stream.Write(ItalianName);
                stream.Write(KoreanName);
                stream.Write(ChineseName);
                stream.Write(PortugueseName);
                stream.Write(EnglishDescription);
                stream.Write(JapaneseDescription);
                stream.Write(GermanDescription);
                stream.Write(FrenchDescription);
                stream.Write(SpanishDescription);
                stream.Write(ItalianDescription);
                stream.Write(KoreanDescription);
                stream.Write(ChineseDescription);
                stream.Write(PortugueseDescription);
                stream.Write(ScenarioPath);
                stream.Write(SortOrder);
                stream.Write(Flags);
                stream.Write(unused0);
                stream.Write(MaxTeamsNone);
                stream.Write(MaxTeamsCTF);
                stream.Write(MaxTeamsSlayer);
                stream.Write(MaxTeamsOddball);
                stream.Write(MaxTeamsKOTH);
                stream.Write(MaxTeamsRace);
                stream.Write(MaxTeamsHeadhunter);
                stream.Write(MaxTeamsJuggernaught);
                stream.Write(MaxTeamsTerritories);
                stream.Write(MaxTeamsAssault);
                stream.Write(unused1);
            }
        }

        public static LevelData Read(MapStream map, int scnrOffset)
        {
            if (map.ReadReflexiveAt(scnrOffset + Offset) == 0) return null;

            LevelData l = new LevelData();
            l.LevelDescription = map.ReadDependancy();
            
            map.PushBookmark();
            
            if(map.ReadReflexive() > 0)
            {
                l.CampaignLevel = new CampaignLevelData();
                l.CampaignLevel.ReadFrom(map);
            }
            
            map.PopBookmark();

            if (map.ReadReflexive() > 0)
            {
                l.MultiplayerLevel = new MultiplayerLevelData();
                l.MultiplayerLevel.ReadFrom(map);
            }

            return l;
        }

        public void WriteTo(BaseStream stream)
        {
            stream.Write(LevelDescription.Class);
            stream.Write(0);
            stream.Write(0);
            stream.Write(0);
            stream.Write(0);
            stream.Write(0);
            if (CampaignLevel != null)
                CampaignLevel.WriteTo(stream);
            if (MultiplayerLevel != null)
                MultiplayerLevel.WriteTo(stream);
        }
    }
}
